package top.healthylife.basics.utils.utils;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.ttl.TransmittableThreadLocal;
import lombok.experimental.UtilityClass;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 当前线程租户处理工具
 *
 * @author maoxiaomeng
 */
@UtilityClass
public class TenantContextHolder {

    private final ThreadLocal<String> THREAD_LOCAL_TENANT = new TransmittableThreadLocal<>();
    private final ThreadLocal<List<String>> THREAD_LOCAL_SHARE_TENANT_IDS = new TransmittableThreadLocal<>();

    /**
     * TTL 设置当前线程租户ID
     *
     * @param tenantId 租户id
     */
    public void setTenantId(String tenantId) {
        THREAD_LOCAL_TENANT.set(tenantId);
    }

    /**
     * 获取当前线程租户ID
     *
     * @return 租户id
     */
    public String getTenantId() {
        return THREAD_LOCAL_TENANT.get();
    }

    public void clear() {
        THREAD_LOCAL_TENANT.remove();
    }

    /**
     * 当前线程共享数据租户id集合
     *
     * @return 当前线程共享数据租户id集合
     */
    public List<String> getShareTenantIds() {
        return Optional.ofNullable(THREAD_LOCAL_SHARE_TENANT_IDS.get()).orElse(new ArrayList<>());
    }

    /**
     * 添加当前线程共享数据租户id集合
     * <p>
     * <p>
     * 如果设置了租户共享，则当前线程涉及到的 INSERT INTO SELECT,DELETE,UPDATE,SELECT都会生效，请根据业务警慎使用。
     * 如
     * <sql>
     * SELECT * FROM `demo` WHERE tenant_id IN ('1','2','3');
     * DELETE FROM `demo` WHERE `name` = 'ha' AND tenant_id IN ('1','2','3');
     * UPDATE `demo` SET `name`='ha' WHERE `name` = 'hei' AND tenant_id IN ('1','2','3');
     * INSERT INTO `demo`(`name`) SELECT `name` FROM `demo2` WHERE tenant_id IN ('1','2','3');
     * </sql>
     * <p>
     * <p>
     * 建议操作方式，在需要的代码片段处使用，使用完后及时{@link #clearShareTenantIds()}避免后续的sql也参与了租户共享，代码示例如：
     * <code>
     * //----获取当前租户直接下级租户的渠道商----
     * //1.获取当前租户直接下级租户 如 ["1","2","3"]
     * List<String> directSubordinateTenantIds = upmsTenantServiceApi.getTenantsByType(ShareTenantType.DirectSubordinate).getData();
     * //2.设置租户共享
     * TenantContextHolder.addShareTenantIds(directSubordinateTenantIds);
     * //3.进行渠道商查询  解析sql为：SELECT * FROM distributor WHERE tenant_id IN ('1','2','3');
     * List<Distributor> distributorList = distributorsService.list();
     * //4.使用完后销毁，不影响后续的sql。
     * TenantContextHolder.clearShareTenantIds();
     * //。。。。接着其他sql操作
     * </code>
     *
     * @param shareTenantIds 共享数据租户id集合
     */
    public void addShareTenantIds(List<String> shareTenantIds) {
        List<String> ttl = Optional.ofNullable(THREAD_LOCAL_SHARE_TENANT_IDS.get()).orElse(new ArrayList<>());
        if (ObjectUtil.isNotEmpty(shareTenantIds)) {
            ttl.addAll(shareTenantIds);
            ttl = ttl.stream().filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList());
            THREAD_LOCAL_SHARE_TENANT_IDS.set(ttl);
        }
    }

    /**
     * 移除当前线程共享数据租户id集合
     *
     * @param shareTenantIds 共享数据租户id集合
     */
    public void removeShareTenantIds(List<String> shareTenantIds) {
        List<String> ttl = Optional.ofNullable(THREAD_LOCAL_SHARE_TENANT_IDS.get()).orElse(new ArrayList<>());
        if (ObjectUtil.isNotEmpty(shareTenantIds)) {
            shareTenantIds = shareTenantIds.stream().filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList());
            ttl.removeAll(shareTenantIds);
            THREAD_LOCAL_SHARE_TENANT_IDS.set(ttl);
        }
    }

    /**
     * clear 共享租户id
     */
    public void clearShareTenantIds() {
        THREAD_LOCAL_SHARE_TENANT_IDS.remove();
    }

    /**
     * 清空
     */
    public void clearAll() {
        clear();
        clearShareTenantIds();
    }
}
